package com.github.soiff.shadow.endpoints;

import com.github.soiff.shadow.error.Errors;
import com.github.soiff.shadow.plugins.Controller;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.actuate.endpoint.EndpointProperties;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * Created by Soiff on 2016/05/19.
 *
 * @author : Soiff
 */
@ConfigurationProperties(prefix = "endpoints."+ PluginEndpoint.endpoint)
public class PluginEndpoint implements MvcEndpoint, EnvironmentAware {
    public final static String endpoint = "plugin";

    @Autowired
    private Controller controller;

    @Getter @Setter
    private String workingDirectory = "temp";

    @Getter @Setter
    @NotNull
    @Pattern(regexp = "/.*", message = "Path must start with /")
    private String path = "/"+endpoint;

    private Environment environment = null;
    private Boolean sensitive = null;

    @Getter @Setter
    private boolean enabled = true;

    @Override
    public String getPath() {
        return endpoint;
    }

    @Override
    public boolean isSensitive() {
        return EndpointProperties.isSensitive(this.environment, this.sensitive, true);
    }

    @Override
    public Class<? extends Endpoint> getEndpointType() {
        return null;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @ResponseBody
    @RequestMapping(
        method = {RequestMethod.GET},
        produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}
    )
    public Object invoke(
        HttpServletRequest request,
        HttpServletResponse response,
        @RequestParam(value = "uri") String uri,
        @RequestParam(value = "alias") String alias,
        @RequestParam(value = "act", required = false) String act
    )
        throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException
    {
        if (!isEnabled()) {
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return null;
        }

        final File file = new File(uri);
        final String classpath = workingDirectory + File.separator + file.getName();
        final Map<String, Errors> result = controller.registerPlugin(alias, uri, classpath);
        return result;
    }
}
